; load formats: ply, 3ds, asc, md2, lwo
; read triangles and points
; read tp     in : esi = ptr to data
;                  ebx = file size
;             out: eax = vertices count
;                  ebx = tris count
; read format in : eax = vertices numbe
;                  ebx = tirs number
;                  esi = ptr to data
;                  edi = ptr to tris list
;                  edx = ptr to verts list
;                  ecx = file size
;                  xmm0 = 'b' = big endian
read_lwo_tp:
   ; in:
   ;     esi = ptr to data
   ;     ebx = file size
   ; out:
   ;     eax = points count
   ;     ebx = tris count
   cld
   add   ebx,esi
   sub   ebx,6
   lodsd
   cmp   eax,'FORM'
   jne   .fail
  @@:
   cmp   esi,ebx
   jnb   .fail
   lodsb
   cmp   al,'P'
   jne   @b
   dec   esi
   lodsd
   cmp   eax,'PNTS'
   je    @f
   sub   esi,3
   jmp   @b
  @@:
   lodsd
   bswap eax
   mov   edi,eax
   xor   edx,edx
   mov   ecx,12
   idiv  ecx
   push  eax      ; pts count
   add   esi,edi
   sub   esi,8
  @@:
   cmp   esi,ebx
   jnb   .fail
   lodsb
   cmp   al,'P'
   jne   @b
   dec   esi
   lodsd
   cmp   eax,'POLS'
   je    @f
   sub   esi,3
   jmp   @b
  @@:
   lodsd
   bswap eax
   mov   ecx,10
   xor   edx,edx
   idiv  ecx
   xchg  ebx,eax  ; faces cnt
   pop   eax
   xor   ecx,ecx
   ret
 .fail:
   mov   cl,'f'
ret
;==========================================================
read_lwo:
   ; in:
   ;    eax = vertices number
   ;    ebx = tirs number
   ;    esi = ptr to data
   ;    edi = ptr to tris list
   ;    edx = ptr to verts list
   ;    ecx = file size
   push    ebp
   mov     ebp,esp
   .tc        equ [ebp-4]
   .pc        equ [ebp-8]
   .t_ptr     equ [ebp-12]
   .p_ptr     equ [ebp-16]
   .start     equ [ebp-20]
   .file_size equ [ebp-24]
   .endd      equ [ebp-28]

   push  ebx eax edi edx esi ecx

   cld
   add   ecx,esi
   sub   ecx,6
   push  ecx
;   mov   .endd,ecx
   lodsd
   cmp   eax,'FORM'
   jne   .fail
  @@:
   cmp   esi,ecx
   jnb   .fail
   lodsb
   cmp   al,'P'
   jne   @b
   dec   esi
   lodsd
   cmp   eax,'PNTS'
   je    @f
   sub   esi,3
   jmp   @b
 @@:
   cmp   esi,.endd
   jnb   .fail
   lodsd
   mov   ecx,.pc
   lea   ecx,[ecx*3]
   mov   edi,edx   ; p_ptr
   cld
  @@:
   cmp   esi,.endd
   jnb   .fail
   lodsd
   bswap eax
   stosd
   loop  @b

   sub    esi,8
  @@:
   cmp    esi,.endd   ;ecx
   jnb    .fail
   lodsb
   cmp    al,'P'
   dec    esi
   lodsd
   cmp    eax,'POLS'
   je     @f
   sub    esi,2
   jmp    @b
  @@:
   lodsd

   mov    ecx,.tc
   mov    edi,.t_ptr
 @@:
   cmp    esi,.endd
   jnb    .fail
   lodsw
   xchg   ah,al
   cmp    ax,3
   jne    .fail
   xor    eax,eax
   lodsw
   xchg   ah,al
   stosd
   lodsw
   xchg   ah,al
   stosd
   lodsw
   xchg   ah,al
   stosd
   lodsw
   loop   @b

   xor    ecx,ecx
   jmp    .en
 .fail:
   mov    cl,'f'
 .en:
   mov    esp,ebp
;   pop    ebp
;ret
   leave
;========================================================
read_md2_tp:
   ; in:
   ;     esi = ptr to data
   ; out:
   ;     eax = points count
   ;     ebx = tris count
   ; additional info: dword[esi+64] = file size
   cld
   lodsd
   cmp    eax,'IDP2'
   jne    .fail
   add    esi,20
   lodsd
   mov    ebx,eax
   add    esi,4
   lodsd
   xchg   eax,ebx
   ret
 .fail:
   mov    cl,'f' ; cl = 'f' => fail
ret
;=======================================================
read_md2:
   ; in:
   ;    eax = vertices number
   ;    ebx = tirs number
   ;    esi = ptr to data
   ;    edi = ptr to tris list
   ;    edx = ptr to verts list
   .tc     equ [ebp-4]
   .pc     equ [ebp-8]
   .t_ptr  equ [ebp-12]
   .p_ptr  equ [ebp-16]
   .start  equ [ebp-20]

   push    ebp
   mov     ebp,esp
;   sub     esp,20
   push    ebx eax edi edx esi  ; ecx
   cld
;   mov    .pc,eax
;   mov    .tc,ebx
;   mov    .t_ptr,edi
;   mov    .p_ptr,edx
;   mov    .start,esi

   add     esi,64-12
   mov     ecx,.tc
   lodsd
   push    esi
   mov     esi,eax
   add     esi,.start
 @@:
   xor     eax,eax
   lodsw
   stosd
   xor     eax,eax
   lodsw
   stosd
   xor     eax,eax
   lodsw
   stosd
   add     esi,6
   loop    @b
   pop     esi
   lodsd
   add     eax,.start

   movups  xmm7,[eax]
   movups  xmm6,[eax+12]
   ; 0 -  12 bytes = scale
   ; 12 - 24 bytes = translate
   ; 24 - 30 bytes = 16 bytes frame name
   ; 12 + 12 + 16 = 40
   add       eax,40
   mov       edi,.p_ptr
   mov       esi,eax
   mov       ecx,.pc
   xorps     xmm1,xmm1
 @@:
   movlps    xmm0,[esi]
   punpcklbw xmm0,xmm1
   punpcklwd xmm0,xmm1
   cvtdq2ps  xmm0,xmm0
   mulps     xmm0,xmm7
   addps     xmm0,xmm6
   movups    [edi],xmm0
   add       edi,12
   add       esi,4
   loop      @b

   mov       esp,ebp
;   pop       ebp
;ret
   leave
;=========================================================================
;=========================================================
read_ply_tp:
   ; in:
   ; esi = ptr to data
   ; out:
   ;     eax = points count
   ;     ebx = tris count
   ;     cl  = 'b' means big endian
   .tc     equ [ebp-4]
   .pc     equ [ebp-8]
   .endian equ byte[ebp-12]

   push    ebp
   mov     ebp,esp
   sub     esp,20
   mov     .endian,'l'
   cld
   lodsw
   cmp     ax,'pl'
   jne     .end
   lodsb
   cmp     al,'y'
   jne     .end
 @@:
   inc     esi
   cmp     [esi],dword 'bina'
   jne     @b
 @@:
   inc     esi
   cmp     [esi],dword 'endi'
   jne     @b
   sub     esi,3
   cmp     [esi],word 'le'  ; little
   je      @f
   mov     .endian,'b'
 @@:
   inc     esi
   cmp     [esi],word 'ex'
   jne     @b
   add     esi,3
  @@:
   lodsb
   cmp     al,'0'
   jb      .atoi
   cmp     al,'9'
   jna     @b

 .atoi:
   push    esi
   mov     ebx,esi
   sub     ebx,2
;  atof
;  in ---   [ebx] -> end of ascii string
;  out --   edx  -> desired number
   call    ascii_to_integer
;  cmp     .endian,'l'
;  je      @f
;  bswap   edx
; @@:
   mov     .pc,edx
   pop     esi
  @@:
   inc     esi
   cmp     dword [esi],'face'
   jne     @b
   add     esi,5
  @@:
   lodsb
   cmp     al,'0'
   jb      .atoi2
   cmp     al,'9'
   jna     @b
  @@:
   cmp     al,'0'
   jb      .atoi2
   cmp     al,'9'
   jna     @b
 .atoi2:
   mov     ebx,esi
   sub     ebx,2
   call    ascii_to_integer
   mov     .tc,edx
   mov     eax,.pc
   mov     ebx,edx
   mov     cl,.endian
   mov     dl,'s' ; success
   jmp     .en2
 .end:
   mov     cl,'f' ; fail
 .en2:
   mov     esp,ebp
   pop     ebp
ret
;==================================================================
read_ply:
   ; in:
   ;    eax = vertices number
   ;    ebx = tirs number
   ;    esi = ptr to data
   ;    edi = ptr to tris list
   ;    edx = ptr to verts list
   ;    xmm0 = byte 'b' means big endian

   .tc     equ [ebp-4]
   .pc     equ [ebp-8]
   .t_ptr  equ [ebp-12]
   .p_ptr  equ [ebp-16]
   .endian equ byte[ebp-17]

   push    ebp
   mov     ebp,esp
   push    ebx eax edi edx esi
   sub     esp,20
   movd    ecx,xmm0
   mov     .endian,cl
   cmp     cl,'b'
   je      @f
   mov     .endian,'l'
  @@:
   cld
  @@:
   inc     esi
   cmp     [esi],dword 'ader'
   jne     @b
   add     esi,5

   mov     edi,.p_ptr
   mov     ecx,.pc
   lea     ecx,[ecx*3]

   cld
   cmp     .endian,'b'
   je      @f
   rep     movsd
   jmp     .le1
 @@:
   lodsd
   bswap   eax
   stosd
   loop    @b
 .le1:
   mov     edi,.t_ptr
   mov     ecx,.tc
   cmp     .endian,'b'
   je      .be1
  @@:
   lodsb
   movsd
   movsd
   movsd
   loop    @b
   jmp     .le2

 .be1:
   lodsb
 .be11:
   lodsd
   bswap   eax
   stosd
   lodsd
   bswap   eax
   stosd
   lodsd
   bswap   eax
   stosd
   lodsd
   loop   .be11

  .le2:
; end success
;   mov     dl,'s'
;   jmp     .en
; .end:
;   mov     dl,'f' ; fail
 .en:
   mov     esp,ebp
   pop     ebp
ret

;===================================================================
read_3ds_tp:
                ; in:   esi = ptr to 3ds file
                ;       ebx = file size
                ;       edx = 1 -> read chunks count
                ; out:  eax = points count     ; eax
                ;       ebx = triangles count
                ;       edx = chunks number
                ;       cl == 'f' = read fail
                push ebp
                mov  ebp,esp
                sub  esp,36

               .tri_count  equ [ebp-4]
               .vert_count equ [ebp-8]
               .FileSize   equ [ebp-12]
               .EndFile    equ [ebp-16]
               .fe         equ [ebp-16]
               .chunks_c   equ dword[ebp-20]
               .rch        equ dword[ebp-24]
               .fem2       equ dword[ebp-28]
               .fem1       equ dword[ebp-32]

                xor      eax,eax
                mov     .rch,edx
                mov     .chunks_c,eax
                mov     .FileSize,ebx
                xor     ebx,ebx
                mov     .vert_count,ebx
                mov     .tri_count,ebx
                cmp     [esi],word 4D4Dh
                je      @f ;Must be legal .3DS file
                xor     eax,eax
                jmp     .fail
             @@:
                mov     eax,dword[esi+2]
                cmp     eax,.FileSize ;This must tell the length
                je      @f
                xor     eax,eax
                jmp     .fail

             @@:
                add     eax,esi
                mov     .EndFile,eax
                dec     eax
                mov     .fem1,eax
                dec     eax
                mov     .fem2,eax
                xor     eax,eax
                add     esi,6
             @@:
                cmp     [esi],word 3D3Dh
                je      @f
                cmp     esi,.fem2 ;.EndFile
                ja      .ex1
                add     esi,[esi+2]
                jmp     @b
             @@:
                add     esi,6
             .find4k:
                cmp     [esi],word 4000h
                je      @f
                cmp     esi,.fem2
                ja     .ex1

                add     esi,[esi+2]
                cmp     esi,.fe  ;.FileSize
                jc      .find4k
                jmp     .exit
             @@:
                add     esi,6
             @@:
                cmp     esi,.fe
                ja      .ex1
                cmp     [esi],byte 0
                je      @f
                inc     esi
                jmp     @b
             @@:
                inc     esi
             @@:
                cmp     esi,.fe ;m2
                ja      .ex1
                cmp     [esi],word 4100h
                je      @f
                cmp     esi,.fem2
                ja     .ex1             ; some 3ds files needs thise check

                add     esi,[esi+2]
                jmp     @b
             @@:
                add     esi,6
             @@:
                cmp     esi,.fe ;m2
                ja      .ex1
                cmp     [esi],word 4110h
                je      @f
                cmp     esi,.fem2
                ja      .ex1
                cmp     dword[esi+2],eax
                je      .find4k

                add     esi,[esi+2]
                jmp     @b
             @@:
                movzx   ecx,word[esi+6]
                add     .vert_count,ecx
                mov     edx,ecx
                add     esi,8
                imul    ecx,6
                jc      .ex1

                add     ebx,ecx
                jc      .ex1
                add     ecx,ecx
                add     esi,ecx
                jc      .ex1
             @@:
                cmp     esi,.fe
                jae     .ex1
                cmp     [esi],word 4120h
                je      @f
                cmp     esi,.fem2        ; some 3ds files needs thise check
                ja      .ex1
                add     esi,[esi+2]
                jmp     @b
             @@:
                movzx   ecx,word[esi+6]
                inc     .chunks_c
                add     .tri_count,ecx
                add     esi,8
                shl     ecx,3
                add     esi,ecx
                jmp     .find4k
             .ex1:
             .exit:
                mov     eax,dword .vert_count
                mov     ebx,dword .tri_count
                xor     edx,edx
                cmp     .rch,1
                jne     @f
                mov     edx,.chunks_c
             @@:
                jmp     .en
             .fail:
                mov     cl,'f'
             .en:
                mov     esp,ebp
                pop     ebp
                ret

;========================================================================

read_from_file:
               ; read from 3ds file
               ; in:
               ; eax = vertices number
               ; ebx = tris number
               ; esi = ptr to data
               ; edi = ptr to tris list
               ; edx = ptr to verts list
               ;; This procedure coded orginally by Madis Kalme
               ;; Thanks a lot Madis!!!
               ;; I extend it to work with objects above 65536 vertices
                push         ebp
                mov          ebp,esp
                sub          esp,48

             .triangles_p equ [ebp-4]
             .vert_p      equ [ebp-8]
             .file        equ [ebp-12]
             .file_end    equ [ebp-16]
             .fe          equ [ebp-16]    ; alias
             .vert_cnt    equ [ebp-20]
             .tri_cnt     equ [ebp-24]
             .cur_ch      equ [ebp-28]
             .cur_chp     equ dword[ebp-32]
             .cccnt       equ [ebp-36]
             .fem2        equ dword[ebp-40]
             .fem1        equ dword[ebp-44]

                mov     .triangles_p,edi
                mov     .vert_p,edx
                mov     .file,esi
                xor     ebx,ebx
                mov     dword .vert_cnt,ebx
                mov     dword .tri_cnt,ebx
             ;   mov     esi,ecx
                cmp     [esi],word 4D4Dh
                jne     .exit ;Must be legal .3DS file
                ;      cmp     dword[esi+2],EndFile-SourceFile
                ;      jne     .exit ;This must tell the length
                mov     eax,dword[esi+2]
                ;      cmp     eax,[fsize]
                ;      jne     .exit
                add     eax,esi
                mov     .file_end,eax
                dec     eax
                mov     .fem1,eax
                dec     eax
                mov     .fem2,eax
                xor     eax,eax
                mov     .cccnt,eax
                add     esi,6
             @@:
                cmp     [esi],word 3D3Dh
                je      @f
                cmp     esi,.fem2       ; some 3ds files needs thise check
                ja      .ex1
                add     esi,[esi+2]
                jmp     @b
             @@:
                add     esi,6
             .find4k:
                cmp     [esi],word 4000h
                je      @f
                cmp     esi,.fem2
                ja     .ex1
                add     esi,[esi+2]
                cmp     esi,.file_end
                jc      .find4k
                jmp     .exit
             @@:
                add     esi,6
             @@:
                cmp     [esi],byte 0
                je      @f
                cmp     esi,.fem1
                ja     .ex1
                inc     esi
                jmp     @b
             @@:
                inc     esi
             @@:
                cmp     esi,.fe
                ja      .ex1
                cmp     [esi],word 4100h
                je      @f
                cmp     esi,.fem2
                ja     .ex1          ; some 3ds files needs thise check
                add     esi,[esi+2]
                jmp     @b
             @@:
                add     esi,6
             @@:
                cmp     esi,.fe  ;m2
                ja      .ex1
                cmp     [esi],word 4110h
                je      @f

                cmp     dword[esi+2],0
                je      .find4k

                add     esi,[esi+2]
                jmp     @b
             @@:
                movzx    ecx,word[esi+6]       ; word
                add      .vert_cnt,ecx
                mov      edx,ecx
                add      esi,8
                push     edi
                mov      edi,.vert_p
                or       ecx,ecx
                jz       .done
             @@:
                cld
                lea      ecx,[ecx*3]
                rep      movsd
                mov      .vert_p,edi
             .done:
                pop      edi
             @@:
                cmp      [esi],word 4120h
                je       @f
                add      esi,[esi+2]
                jmp      @b
             @@:
                movzx    ecx,word[esi+6]
                add      .tri_cnt,ecx
                add      esi,8
                movlps   xmm1,.cccnt  ;eax
                shufps   xmm1,xmm1,0
                movlps   xmm5,.cur_ch
                shufps   xmm5,xmm5,0
             @@:
             .two:
                xorps     xmm3,xmm3
                movlps    xmm0,[esi]
                punpcklwd xmm0,xmm3 ;[the_zero]
                paddd     xmm0,xmm1

                movlps    [edi],xmm0
                movhlps   xmm0,xmm0
                movss     [edi+8],xmm0
                add       edi,12
                add       esi,8

             @@:
                loop      .two
                inc       dword .cur_ch
                add       .cccnt,edx
                jmp       .find4k
             .ex1:
                or         eax,-1 ;<---mark if OK
             .exit:
                mov        eax,dword .vert_cnt
                mov        ebx,dword .tri_cnt
                mov        edx,.file_end
                mov        esp,ebp
                pop        ebp
                ret
;===================================================================
read_asc_tp:
   ; in:
   ;     esi = ptr to data
   ; out:
   ;     eax = points count
   ;     ebx = tris count

    push  ebp
    mov   ebp,esp
    sub   esp,12
    .tc   equ [ebp-4]   ;  tris number/count
    .vc   equ [ebp-8]   ;  verts number/count

    mov   eax,esi
  .find_vert:
    cmp   dword[eax],'Vert'
    je    @f
    inc   eax
    jmp   .find_vert
  @@:
    add    eax,4
    cmp    dword[eax],'ices'
    jne    .find_vert
    add    eax,3
  @@:
    inc    eax
    cmp    byte[eax],'0'           ; search end of ascii number of vertices string
    jb     @b
    cmp    byte[eax],'9'
    ja     @b
;    eax - start ascii number
  @@:
    inc    eax
    cmp    byte[eax],'0'
    jb    .convert1
    cmp    byte[eax],'9'
    ja    .convert1
    jmp    @b
  .convert1:
    dec    eax
    mov    ebx,eax
    push   eax
    call   ascii_to_integer
    mov    .pc,edx
    pop    eax
  @@:
    inc    eax
    cmp    dword[eax],'Face'
    jne    @b
    add    eax,3
  @@:
    inc    eax
    cmp    byte[eax],'0'
    jb     @b
    cmp    byte[eax],'9'
    ja     @b
   ;    eax - start ascii number
  @@:
    inc    eax
    cmp    byte[eax],'0'
    jb    .convert2
    cmp    byte[eax],'9'
    ja     .convert2
    jmp    @b
   ;  eax - end ascii number
  .convert2:
    dec    eax
    mov    ebx,eax
    call   ascii_to_integer
    mov    .tc,edx
    mov    ebx,edx
    mov    eax,.pc
    mov    esp,ebp
    pop    ebp
ret
;=====================================================================
read_asc:
; read format in : eax = vertices numbe
;                  ebx = tris number
;                  esi = ptr to data
;                  edi = ptr to tris list
;                  edx = ptr to verts list
    push    ebp
    mov     ebp,esp
    sub     esp,16
   .tc      equ [ebp-4]
   .pc      equ [ebp-8]
   .t_ptr   equ [ebp-12]
   .p_ptr   equ [ebp-16]

;    push     ebx eax edi edx
    mov     .pc,eax
    mov     .tc,ebx
    mov     .t_ptr,edi
    mov     .p_ptr,edx
    mov     eax,esi
  .find_vert:
    cmp     dword[eax],'Vert'
    je      @f
    inc     eax
    jmp     .find_vert
  @@:
    add     eax,4
    cmp     dword[eax],'ices'
    jne     .find_vert
    add     eax,4
  @@:
    inc     eax
    cmp     dword[eax],'Face'
    jne     @b
    add     eax,3
  @@:
    inc     eax
    cmp     byte[eax],'0'
    jb      @b
    cmp     byte[eax],'9'
    ja      @b
   ;    eax - start ascii number
  @@:
    inc     eax
    cmp     byte[eax],'0'
    jb      .convert2
    cmp     byte[eax],'9'
    ja      .convert2
    jmp     @b
   ;  eax - end ascii number
  .convert2:
    dec     eax
    mov     ebx,eax
  @@:
    inc     eax
    cmp     dword[eax],'Vert'
    jnz     @b
    inc     eax
    mov     edi,.p_ptr
    xor     ebx,ebx
  .decode_vertices:
    push    ebx
  @@:
    inc     eax
    cmp     dword[eax],'Vert'
    jne     @b
    xor     ecx,ecx
  .decode_coord:
    push    ecx
  @@:
    inc     eax
    mov     dl,byte[eax]
    cmp     dl,byte[XYZpartices+ecx]
    jne     @b
  @@:
    inc     eax
    cmp     byte[eax],'.'
    je      .readF
    cmp     byte[eax],'-'
    je      .readF
    cmp     byte[eax],'0'
    jb      @b
    cmp     byte[eax],'9'
    ja      @b
  .readF: ; read float
    mov     esi,eax
    push    eax
    push    ecx
    call    atof   ; eax - desired dword float
    stosd
    pop     ecx
    pop     eax
  ;  movss  [edi],xmm7
  ;  add    edi,4

    pop     ecx
    inc     ecx
    cmp     ecx,3
    jne     .decode_coord
    pop     ebx
    inc     ebx
    cmp     ebx,.pc
    jne     .decode_vertices
    mov     esi,eax
  @@:
    inc     esi
    cmp     dword[esi],'Face'
    jne     @b
    xor     edx,edx
    mov     edi,.t_ptr
    cld
  .decode_face:
    push    edx
  @@:
    inc     esi
    cmp     dword[esi],'Face'
    jne     @b
  @@:
    inc   esi
    cmp   byte[esi],'0'    ; face number start
    jb    @b
    cmp   byte[esi],'9'
    ja    @b
  @@:
    inc    esi
    cmp    byte[esi],'0'
    jb    @f
    cmp    byte[esi],'9'   ; face number end
    ja    @f
    jmp   @b
  @@:
    xor   ecx,ecx
  .next_vertex_number:

    push  ecx
  @@:
    inc   esi
    cmp   byte[esi],'0'
    jb    @b
    cmp   byte[esi],'9'
    ja    @b
    ;    eax - start ascii number
  @@:
    inc    esi
    cmp    byte[esi],'0'
    jb    @f
    cmp    byte[esi],'9'
    ja    @f
    jmp   @b
   ;  eax - end ascii number
  @@:
    dec   esi
    mov   ebx,esi
    push  esi
    call  ascii_to_integer
    mov   eax,edx
    stosd
    pop   esi
    add   esi,2
    pop   ecx
    inc   ecx
    cmp   ecx,3
    jne   .next_vertex_number
    pop   edx
    inc   edx
    cmp   edx,.tc
    jne   .decode_face
    mov   esp,ebp
    pop   ebp
ret